package org.stfm.texdoclet; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import java.util.Vector; import com.sun.javadoc.ClassDoc; import com.sun.javadoc.DocErrorReporter; import com.sun.javadoc.Doclet; import com.sun.javadoc.ExecutableMemberDoc; import com.sun.javadoc.FieldDoc; import com.sun.javadoc.MemberDoc; import com.sun.javadoc.MethodDoc; import com.sun.javadoc.PackageDoc; import com.sun.javadoc.ParamTag; import com.sun.javadoc.Parameter; import com.sun.javadoc.RootDoc; import com.sun.javadoc.SeeTag; import com.sun.javadoc.Tag; import com.sun.javadoc.ThrowsTag; import com.sun.javadoc.Type; /** * This class provides a Java <code>javadoc</code> Doclet which generates a <TEX * txt="\LaTeXe{}">LaTeX2e</TEX> document out of the java classes that it is * used on. This is convenient for creating printable documentation complete * with cross reference information. <H3>Supported HTML tags</H3> * <dl> * <dt><a> * <dd>including an additional attribut "doprinturl". Since the output of the * doclet should be printable, the href attribut of <A> tags is printed in * parentheses following the link if attribut "doprinturl" is set. Sometimes * this is undesirable, and omitting "doprinturl" attribut will prevent this. * <dt><dl> * <dd>with the associated <dt><dd></dl> tags * <dt><p> * <dd>but not align=center...yet * <dt><br> * <dd>but not clear=xxx * <dt><table> * <dd>including all the associated * <td><th><tr></td></th></tr> * <dt><ol> * <dd>ordered lists * <dt><ul> * <dd>unordered lists * <dt><font> * <dd>font coloring * <dt><pre> * <dd>preformatted text * <dt><code> * <dd>fixed point fonts * <dt><i> * <dd>italized fonts * <dt><b> * <dd>bold fonts * <dt><sub> * <dd>subscript * <dt><sup> * <dd>superscript * <dt><center> * <dd>center * <dt><img> * <dd>image located in java sources (<img src="package path/image name">) * <dl> * <dt>1. example * <dd>converted from JPG: <IMG width="100%" src="doc-files/texdoclet.jpg"> * <dt>2. example * <dd>converted from GIF: <IMG width="100%" src="doc-files/texdoclet.gif"> * </dl> * <dt><img> * <dd>image located in the www: <IMG * src="http://upload.wikimedia.org/wikipedia/commons/9/92/LaTeX_logo.svg"> * </dl> * * <H3>Extra tags</H3> <H4><TEX></H4> A new tag is defined: * <CODE><TEX></CODE>. This tag is useful for passing <TEX * txt="\TeX{}">TeX</TEX> code directly to the <TEX txt="\TeX{}">TeX</TEX> * compiler. The following code: * * <PRE> * * <TEX txt="\[ F\left( x \right) = \int_{ - \infty }^x {\frac{1}{{\sqrt {2\pi } * }}e^{ - \frac{{z^2 }}{2}} dz} \]"> * <BR><BR><B>This alternative text will appear if the javadoc/HTML is parsed * by any other doclet/browser</B><BR><BR></TEX> * </PRE> * <P> * will produce the following result: <TEX txt="\[ F\left( x \right) = \int_{ - * \infty }^x {\frac{1}{{\sqrt {2\pi } }}e^{ - \frac{{z^2 }}{2}} dz} \]"> <BR> * <BR> * <B>This alternative text will appear if the javadoc/HTML is parsed by any * other doclet/browser</B><BR> * <BR> * </TEX> The "alternative" text is ignored by the TeXDoclet, but useful if you * want to use both the TeXDoclet and a regular HTML based doclet. * * <H4><PRE format="markdown"></H4> * * Instead of writing your java documentation in often hard to read HTML code * you can make use of <a * href="http://en.wikipedia.org/wiki/Markdown">Markdown</a> syntax. The HTML * <code><PRE></code> tag is used therefore to prevent your IDE from * automatically reordering your Markdown documentation text. Markdown parsing * is based on the <a href="https://github.com/sirthias/pegdown">Pegdown</a> * implementation. The following code : * * <PRE> * * <PRE format="markdown"> * * some text some text some text some text some text some text some text * * ##### Lists * * - item1 * 1. item11 * 2. item12 * - item1 * * ##### Text formatting * * _emphasis_ and __strong__ and some `code` : * * code line 1 * code line 2 * * some text some text some text some text some text some text some text * * <PRE> * * </PRE> * * will produce the following : <br> * <p> * * <PRE format="md"> * * some text some text some text some text some text some text some text * * ##### Lists * * - item1 * 1. item11 * 2. item12 * - item1 * * ##### Text formatting * * _emphasis_ and __strong__ and some `code` : * * code line 1 * code line 2 * * some text some text some text some text some text some text some text * * </PRE> * * @see HTMLtoLaTeXBackEnd * @see #start(RootDoc) start * @author Gregg Wonderly - C2 Technologies Inc. * @author Soeren Caspersen - XO Software. * @author Stefan Marx */ @SuppressWarnings("restriction") public class TeXDoclet extends Doclet { private static final String PDFLATEX_CMD = "lualatex --interaction=nonstopmode --output-format=pdf "; private static final int PDFLATEX_ITERATIONS = 2; private static final String OUT_FILENAME_DOCS_TEX = "docs.tex"; private static final String OUT_PREAMBLE_SUFFIX = "_preamble"; public static final String SECTION_LEVEL = "section"; public static final String CHAPTER_LEVEL = "chapter"; public static final String SUBSECTION_LEVEL = "subsection"; public static final String DEFAULT_CLASS_FRAME = "none"; public static final String DEFAULT_METHOD_FRAME = "none"; public static final String BOLD = "{\\bf "; // no bold AND truetype support if using textbf ! // public static final String BOLD = "\\textbf{"; // public static final String TRUETYPE = "{\\tt "; public static final String TRUETYPE = "\\texttt{"; // public static final String ITALIC = "{\\it "; public static final String ITALIC = "\\textit{"; /** Writer for writing to output file */ public static PrintWriter os = null; static boolean inherited = true; static Hashtable<String, Package> map2; static Vector<Package> map; static ClassFilter clsFilt; static RootDoc theroot; static String docclass = "report"; static String style = "headings"; static String title; static String date; static String author; static boolean verbose = false; static boolean index = true; static boolean classtree = false; static boolean serial = false; static boolean twosided = false; static double overviewindent = 1.0; static boolean hyperref = false; static boolean pdfhyperref = false; static boolean versioninfo = false; static boolean summaries = true; static String outfile = OUT_FILENAME_DOCS_TEX; static String setupFile = "docsetup.tex"; static String finishFile = "docfinish.tex"; static String packageFile = "docpackage.tex"; static String preambleFile = "docinit.tex"; static File packageDir = null; static Hashtable<String, String> appendencies = new Hashtable<String, String>(); static Hashtable<String, Hashtable<?, ?>> refs = new Hashtable<String, Hashtable<?, ?>>(); static Hashtable<String, Hashtable<?, ?>> externalrefs = new Hashtable<String, Hashtable<?, ?>>(); static boolean includeTexOutputInOtherTexFile = false; static String sectionLevelMax = null; static String[] sectionLevels = new String[3]; static boolean useFieldSummary = true; static boolean useConstructorSummary = true; static boolean useHr = false; static boolean usePackageToc = true; static boolean shortInheritance = false; /** * print writer for extra LaTeX preamble file */ static PrintWriter osPreamble = null; static String outfilePreamble = null; static String imagesPath = null; static String subtitle = null; static String introFile = null; static double tableWidthScale = 0.9; static boolean createPdf = false; static String package_order = null; static String classDeclarationFrame = DEFAULT_CLASS_FRAME; static String methodDeclarationFrame = DEFAULT_CLASS_FRAME; static final String REPLACE_OUT = "_replace_data_"; static final String REPLACE_TITLE = "_replace_title_"; static final String HTML_PDF_WRAPPER = "<!DOCTYPE html><html lang=\"en\" xml:lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><head>" + "<style>" + "html {" + " height: 100%;" + "}" + "body {" + " margin: 0px;" + " height: 100%;" + " overflow: hidden;" + "}" + ".pdfDoc {" + " height: 100%;" + " width: 100%;" + "}" + "</style>" + "<title>" + REPLACE_TITLE + "</title></head><body><object data=\"" + REPLACE_OUT + "\" type=\"application/pdf\" class=\"pdfDoc\"></object></body></html>"; public static void main(String args[]) { // call javadoc try { System.out.println("Creating LaTeX Java documentation ..."); String argsJd[] = new String[args.length + 4]; argsJd[0] = "-docletpath"; argsJd[1] = "./TeXDoclet.jar"; argsJd[2] = "-doclet"; argsJd[3] = TeXDoclet.class.getName(); System.arraycopy(args, 0, argsJd, 4, args.length); // TODO something goes wrong here. javadoc always prints help // output. // execute("javadoc", argsJd); execute("javadoc " + Arrays.toString(argsJd).replace(", ", " ") .replaceAll("[\\[\\]]", ""), null, false); } catch (IOException e1) { e1.printStackTrace(); } catch (InterruptedException e2) { e2.printStackTrace(); } System.out.println("... Done."); } /** * Doclet class method that returns how many arguments would be consumed if * <code>option</code> is a recognized option. * * @param option * the option to check */ public static int optionLength(String option) { if (option.equals("-title")) { return 2; } else if (option.equals("-date")) { return 2; } else if (option.equals("-docclass")) { return 2; } else if (option.equals("-doctype")) { return 2; } else if (option.equals("-author")) { return 2; } else if (option.equals("-texsetup")) { return 2; } else if (option.equals("-texinit")) { return 2; } else if (option.equals("-texfinish")) { return 2; } else if (option.equals("-texpackage")) { return 2; } else if (option.equals("-classfilter")) { return 2; } else if (option.equals("-noinherited")) { return 1; } else if (option.equals("-serial")) { return 1; } else if (option.equals("-nosummaries")) { return 1; } else if (option.equals("-noindex")) { return 1; } else if (option.equals("-tree")) { return 1; } else if (option.equals("-hyperref")) { return 1; } else if (option.equals("-twosided")) { return 1; } else if (option.equals("-pdfhyperref")) { return 1; } else if (option.equals("-version")) { return 1; } else if (option.equals("-treeindent")) { return 2; } else if (option.equals("-link")) { return 3; } else if (option.equals("-nofieldsummary")) { return 1; } else if (option.equals("-noconstructorsummary")) { return 1; } else if (option.equals("-include")) { return 1; } else if (option.equals("-sectionlevel")) { return 2; } else if (option.equals("-hr")) { return 1; } else if (option.equals("-nopackagetoc")) { return 1; } else if (option.equals("-shortinherited")) { return 1; } else if (option.equals("-help")) { HelpOutput.printHelp(); return 1; } else if (option.equals("-output")) { return 2; } else if (option.equals("-imagespath")) { return 2; } else if (option.equals("-subtitle")) { return 2; } else if (option.equals("-texintro")) { return 2; } else if (option.equals("-tablescale")) { return 2; } else if (option.equals("-createpdf")) { return 1; } else if (option.equals("-packageorder")) { return 2; } else if (option.equals("-classdeclrframe")) { return 2; } else if (option.equals("-methoddeclrframe")) { return 2; } System.out.println("unknown TeXDoclet option " + option); // return Standard.optionLength(option); return Doclet.optionLength(option); } /** * Doclet class method that checks the passed options and their arguments * for validity. * * @param args * the arguments to check * @param err * the interface to use for reporting errors */ static public boolean validOptions(String[][] args, DocErrorReporter err) { for (int i = 0; i < args.length; ++i) { if (args[i][0].equals("-output")) { outfile = args[i][1]; } else if (args[i][0].equals("-date")) { date = args[i][1]; } else if (args[i][0].equals("-title")) { title = args[i][1]; } else if (args[i][0].equals("-author")) { author = args[i][1]; } else if (args[i][0].equals("-verbose")) { verbose = true; } else if (args[i][0].equals("-docclass")) { docclass = args[i][1]; } else if (args[i][0].equals("-classfilter")) { String fcl = args[i][1]; try { clsFilt = (ClassFilter) Class.forName(fcl).newInstance(); } catch (Exception ex) { ex.printStackTrace(); System.exit(2); } } else if (args[i][0].equals("-doctype")) { style = args[i][1]; } else if (args[i][0].equals("-texsetup")) { setupFile = args[i][1]; } else if (args[i][0].equals("-texinit")) { preambleFile = args[i][1]; } else if (args[i][0].equals("-texfinish")) { finishFile = args[i][1]; } else if (args[i][0].equals("-texpackage")) { packageFile = args[i][1]; } else if (args[i][0].equals("-noinherited")) { inherited = false; } else if (args[i][0].equals("-serial")) { serial = true; } else if (args[i][0].equals("-nosummaries")) { summaries = false; } else if (args[i][0].equals("-noindex")) { index = false; } else if (args[i][0].equals("-twosided")) { twosided = true; } else if (args[i][0].equals("-tree")) { classtree = true; } else if (args[i][0].equals("-hyperref")) { hyperref = true; } else if (args[i][0].equals("-pdfhyperref")) { pdfhyperref = true; hyperref = true; } else if (args[i][0].equals("-version")) { versioninfo = true; } else if (args[i][0].equals("-treeindent")) { overviewindent = Double.parseDouble(args[i][1]); } else if (args[i][0].equals("-link")) { try { FileInputStream in = new FileInputStream(args[i][2] + ".map"); ObjectInputStream p = new ObjectInputStream(in); Hashtable<?, ?> exref = (Hashtable<?, ?>) p.readObject(); externalrefs.put(args[i][1], exref); } catch (Exception e) { e.printStackTrace(); } } else if (args[i][0].equals("-nofieldsummary")) { useFieldSummary = false; } else if (args[i][0].equals("-noconstructorsummary")) { useConstructorSummary = false; } else if (args[i][0].equals("-include")) { includeTexOutputInOtherTexFile = true; } else if (args[i][0].equals("-sectionlevel")) { sectionLevelMax = args[i][1]; } else if (args[i][0].equals("-hr")) { useHr = true; } else if (args[i][0].equals("-nopackagetoc")) { usePackageToc = false; } else if (args[i][0].equals("-shortinherited")) { shortInheritance = true; } else if (args[i][0].equals("-help")) { // done in optionsLength() // HelpOutput.printHelp(); } else if (args[i][0].equals("-imagespath")) { imagesPath = args[i][1]; } else if (args[i][0].equals("-subtitle")) { subtitle = args[i][1]; } else if (args[i][0].equals("-texintro")) { introFile = args[i][1]; } else if (args[i][0].equals("-tablescale")) { tableWidthScale = Double.parseDouble(args[i][1]); } else if (args[i][0].equals("-createpdf")) { createPdf = true; } else if (args[i][0].equals("-packageorder")) { package_order = args[i][1]; } else if (args[i][0].equals("-classdeclrframe")) { classDeclarationFrame = args[i][1]; } else if (args[i][0].equals("-methoddeclrframe")) { methodDeclarationFrame = args[i][1]; } if (sectionLevelMax != null && !sectionLevelMax.equals(CHAPTER_LEVEL) && !sectionLevelMax.equals(SECTION_LEVEL) && !sectionLevelMax.equals(SUBSECTION_LEVEL)) { System.err.println("Invalid option -sectionlevel" + " (use \"subsection\",\"section\" or \"chapter\")"); return false; } } System.out.println("args parsed"); // return Standard.validOptions(args, err); return Doclet.validOptions(args, err); } /** * Doclet class method that is called by the framework to format the entire * document * * @Override * * @param root * the root of the starting document */ public static boolean start(RootDoc root) { theroot = root; init(); if (!includeTexOutputInOtherTexFile) { printPreamble(os); os.println("\\begin{document}"); if (title != null) { os.println("\\maketitle"); } addFile(os, setupFile, false); os.println("\\sloppy"); os.println("\\addtocontents{toc}{\\protect\\markboth{Contents}{Contents}}"); os.println("\\tableofcontents"); } else { printPreamble(osPreamble); addFile(osPreamble, setupFile, false); } addFile(os, introFile, false); if (root.inlineTags().length > 0) { os.println("\\" + sectionLevels[0] + "*{Introduction}{"); os.println(" \\addcontentsline{toc}{" + sectionLevels[0] + "}{Introduction}"); os.println("\\thispagestyle{empty}"); os.println("\\markboth{Introduction}{Introduction}"); printTags(null, root.inlineTags()); os.println("}"); } ClassDoc[] cls = root.classes(); PackageDoc[] specifiedPackages = root.specifiedPackages(); // Sort the packages if (package_order != null) { String[] pkg = package_order.split(","); for (int i = 0; i < pkg.length; i++) { // Search for pkg[i] in the specifiedPackages int j; boolean found = false; for (j = i; j < specifiedPackages.length; j++) { if (specifiedPackages[j].name().equals(pkg[i])) { found = true; break; } } if (!found) { System.err.println("Package " + pkg + " not found, aborting."); return false; } if (i != j) { // specifiedPackages has to be reordered PackageDoc swap = specifiedPackages[i]; specifiedPackages[i] = specifiedPackages[j]; specifiedPackages[j] = swap; } } } System.out.println("specifiedPackages : " + specifiedPackages.length); for (int i = 0; i < specifiedPackages.length; i++) { Package P = new Package(specifiedPackages[i].name(), specifiedPackages[i]); System.out.println(i + ". " + specifiedPackages[i].name()); map.add(P); map2.put(specifiedPackages[i].name(), P); } if (clsFilt != null) { System.out.println("...Filter Classes with: " + clsFilt); } List<String> added = new ArrayList<String>(); for (int i = 0; i < cls.length; ++i) { ClassDoc cd = cls[i]; if (clsFilt != null && clsFilt.includeClass(cd) == false) { System.out.println("...Filtering out Class: " + cd.qualifiedName()); continue; } Package v; PackageDoc pkgDoc = cd.containingPackage(); String pkg = pkgDoc.name(); if ((v = map2.get(pkg)) == null) { v = new Package(pkg, pkgDoc); map2.put(pkg, v); map.add(v); } if (!added.contains(cd.qualifiedName())) { added.add(cd.qualifiedName()); v.addElement(cd); } else { System.out.println("skipping duplicate class : " + cd.qualifiedName()); } } // Sorting Enumeration<Package> h = map.elements(); while (h.hasMoreElements()) { final Package pkg = h.nextElement(); pkg.sort(); } // Class hierachy if (classtree) { printClassHierarchy(root); } // os.println("\\part{" + // HTMLtoLaTeXBackEnd.fixText((String)groupHeader.get(0)) + "}"); // os.println(HTMLtoLaTeXBackEnd.fixText((String)groupPackages.get(0))); // Packages Enumeration<Package> e = map.elements(); while (e.hasMoreElements()) { final Package pkg = e.nextElement(); // os.println( "\\newpage" ); addFile(os, packageFile, false); os.println("\\" + sectionLevels[0] + "{Package " + HTMLtoLaTeXBackEnd.fixText(pkg.pkg) + "}{"); os.print("\\label{" + refName(makeRefKey(pkg.pkg)) + "}"); if (hyperref) { os.println("\\hypertarget{" + refName(makeRefKey(pkg.pkg)) + "}{}"); } // os.println( // "\\markboth{\\protect\\packagename}{\\protect\\packagename}" ); // os.println( // "\\markboth{\\protect\\packagename \\hspace{.02in} -- \\protect\\classname}{\\protect\\packagename \\hspace{.02in} -- \\protect\\classname}" // ); if (usePackageToc) { if (ITALIC.indexOf("textit") != -1) { os.println("\\hskip -.05in"); } os.println("\\hbox to \\hsize{" + ITALIC + " Package Contents\\hfil Page}}"); if (useHr) { os.println("\\rule{\\hsize}{.7mm}"); } tocForClasses("Interfaces", pkg.interfaces); tocForClasses("Classes", pkg.classes); os.println("\\vskip .1in"); if (useHr) { os.println("\\rule{\\hsize}{.7mm}"); } os.println("\\vskip .1in"); } // The path relative to which <IMG> will be resolved. packageDir = findPackageDir(pkg.pkg, root); // Package comments if (pkg.pkgDoc.inlineTags().length > 0) { printTags(pkg.pkgDoc, pkg.pkgDoc.inlineTags()); if (useHr) { os.println("\\mbox{}\\\\ \\rule{\\hsize}{.7mm}"); } if (useHr) { os.println("\\vskip .1in"); } } // os.println( "\\newpage"); // os.println( // "\\markboth{\\protect\\packagename \\hspace{.02in} -- \\protect\\classname}{\\protect\\packagename \\hspace{.02in} -- \\protect\\classname}" // ); layoutClasses("Interfaces", pkg.interfaces); layoutClasses("Classes", pkg.classes); layoutClasses("Exceptions", pkg.exceptions); layoutClasses("Error", pkg.errors); os.println("}"); } addFile(os, finishFile, false); if (appendencies.size() > 0) { // os.println("\\appendix"); // Iterator it = appendencies.keySet().iterator(); // int i = 0; // while (it.hasNext()) { // os.println("\\" + sectionLevels[0] + "{}{"); // os.println(" \\label{appendix" + (i + 1) + "}"); // String sfa = (String) it.next(); // // System.out.println(sfa); // addFile(os, sfa, true); // os.println("}"); // i++; // } os.println("\\begin{appendix}"); Iterator<String> it = appendencies.keySet().iterator(); int i = 0; while (it.hasNext()) { String sfa = it.next(); File f = new File(sfa); String fname = f.getName().replace("_", "\\_"); System.out.println(fname); os.println("\\" + sectionLevels[0] + "{File " + fname + "}{"); os.println(" \\label{appendix" + (i + 1) + "}"); addFile(os, sfa, true); os.println("}"); i++; } os.println("\\end{appendix}"); } // os.println("\\markboth{}{}"); if (index) { os.println("\\printindex"); } if (!includeTexOutputInOtherTexFile) { os.println("\\end{document}"); } finish(); return true; } static void init() { map2 = new Hashtable<String, Package>(); map = new Vector<Package>(); try { os = new PrintWriter(new FileWriter(outfile)); } catch (Exception ex) { ex.printStackTrace(); } try { if (includeTexOutputInOtherTexFile) { outfilePreamble = outfile .substring(0, outfile.lastIndexOf(".")) + OUT_PREAMBLE_SUFFIX + ".tex"; osPreamble = new PrintWriter(new FileWriter(outfilePreamble)); } } catch (Exception ex) { ex.printStackTrace(); } initSections(); } static void initSections() { if (sectionLevelMax == null) { if (!includeTexOutputInOtherTexFile) { if (docclass.equals("scrreprt") || docclass.equals("report")) { sectionLevelMax = CHAPTER_LEVEL; } else if (docclass.equals("scrartcl") || docclass.equals("article")) { sectionLevelMax = SECTION_LEVEL; } else { sectionLevelMax = SECTION_LEVEL; } } else { sectionLevelMax = SECTION_LEVEL; } } if (sectionLevelMax.equals(CHAPTER_LEVEL)) { sectionLevels[0] = "chapter"; sectionLevels[1] = "section"; sectionLevels[2] = "subsection"; } else if (sectionLevelMax.equals(SECTION_LEVEL)) { sectionLevels[0] = "section"; sectionLevels[1] = "subsection"; sectionLevels[2] = "subsubsection"; } else if (sectionLevelMax.equals(SUBSECTION_LEVEL)) { sectionLevels[0] = "subsection"; sectionLevels[1] = "subsubsection"; sectionLevels[2] = "subsubsection"; } } static void printPreamble(PrintWriter os) { // this is not our job if including in other document if (!includeTexOutputInOtherTexFile) { if (docclass.equals("scrreprt") || docclass.equals("scrartcl")) { os.println("\\documentclass[11pt,a4paper,titlepage,smallheadings," + "headinclude,headsepline,DIV13,BCOR12.5mm"); } else { os.print("\\documentclass[11pt,a4paper"); } if (twosided) { os.print(",twoside,openright"); } os.println("]{" + docclass + "}"); } printPreambleUsePackages(os); printPreambleListingsOptions(os); printPreambleIfPfd(os); printPreambleNewCommands(os); printPreambleTitle(os); // os.println("\\addtocontents{toc}{\\protect\\thispagestyle{empty}}"); // os.println("\\addtocontents{toc}{\\protect\\def\\protect\\packagename{}}"); // os.println("\\addtocontents{toc}{\\protect\\def\\protect\\classname{}}"); os.println("\\chardef\\textbackslash=`\\\\"); if (index) { os.println("\\makeindex"); } addFile(os, preambleFile, false); } static void printPreambleUsePackages(PrintWriter os) { os.println("\\usepackage{color}"); os.println("\\usepackage{ifthen}"); if (index) { os.println("\\usepackage{makeidx}"); } os.println("\\usepackage{ifpdf}"); os.println("\\usepackage[" + style + "]{fullpage}"); os.println("\\usepackage{listings}"); } static void printPreambleListingsOptions(PrintWriter os) { os.println("\\lstset{language=Java,breaklines=true}"); } static void printPreambleTitle(PrintWriter os) { if (date == null && !includeTexOutputInOtherTexFile) { os.println("\\date{\\today}"); } else { os.println("\\date{" + date + "}"); } if (title != null) { if (subtitle == null) { os.println("\\title{" + title + "}"); } else { os.println("\\title{" + title + "\\bigskip\\\\ \\Large " + subtitle + "}"); } } if (author != null) { os.println("\\author{" + author + "}"); } } static void printPreambleIfPfd(PrintWriter os) { os.println("\\ifpdf \\usepackage[pdftex, pdfpagemode={UseOutlines}," + "bookmarks,colorlinks,linkcolor={blue},plainpages=false,pdfpagelabels," + "citecolor={red},breaklinks=true]{hyperref}"); os.println(" \\usepackage[pdftex]{graphicx}"); os.println(" \\pdfcompresslevel=9"); os.println(" \\DeclareGraphicsRule{*}{mps}{*}{}"); os.println("\\else"); os.println(" \\usepackage[dvips]{graphicx}"); os.println("\\fi\n"); } static void printPreambleNewCommands(PrintWriter os) { os.println("\\newcommand{\\entityintro}[3]{%"); os.println(" \\hbox to \\hsize{%"); os.println(" \\vbox{%"); os.println(" \\hbox to .2in{}%"); os.println(" }%"); os.println(" " + BOLD + " #1}%"); os.println(" \\dotfill\\pageref{#2}%"); os.println(" }"); os.println(" \\makebox[\\hsize]{%"); os.println(" \\parbox{.4in}{}%"); os.println(" \\parbox[l]{5in}{%"); os.println(" \\vspace{1mm}%"); os.println(" #3%"); os.println(" \\vspace{1mm}%"); os.println(" }%"); os.println(" }%"); os.println("}"); if (useHr) { os.println("\\newcommand{\\divideents}[1]{\\vskip -1em\\indent\\rule{2in}{.5mm}}"); } os.println("\\newcommand{\\refdefined}[1]{"); os.println("\\expandafter\\ifx\\csname r@#1\\endcsname\\relax"); os.println("\\relax\\else"); os.println("{$($in \\ref{#1}, page \\pageref{#1}$)$}\\fi}"); } /** * Adds an entire file (HTML or LaTeX). * * @param fixText * Should be true if the file contains HTML. */ static boolean addFile(PrintWriter os, String name, boolean fixText) { if (name == null) { return true; } try { File f = new File(name); if (f.exists() == false) { if (verbose) { System.out.println("Can not open: " + f); } return false; } BufferedReader rd = new BufferedReader(new FileReader(f)); try { StringBuffer buf = new StringBuffer((int) f.length()); String str; while ((str = rd.readLine()) != null) { buf.append(str + "\n"); } if (fixText) { os.println(HTMLtoLaTeXBackEnd.fixText(buf.toString())); } else { os.println(buf.toString()); } } finally { rd.close(); } } catch (Exception ex) { ex.printStackTrace(); return false; } return true; } /** * Produces a table-of-contents for classes. */ static void tocForClasses(String title, Vector<ClassDoc> v) { if (v.size() > 0) { os.println("\\vskip .13in"); os.println("\\hbox{" + BOLD + " " + HTMLtoLaTeXBackEnd.fixText(title) + "}}"); for (int i = 0; i < v.size(); ++i) { ClassDoc cd = v.elementAt(i); os.print("\\entityintro{" + HTMLtoLaTeXBackEnd.fixText(cd.name()) + "}" + "{" + refName(makeRefKey(cd.qualifiedName())) + "}" + "{"); printTags(cd.containingPackage(), cd.firstSentenceTags()); os.println("}"); } } } /** * Produces a LaTeX referencekey from a Java identifier. */ static String refName(String key) { return key; } static void printClassHierarchy(RootDoc root) { os.println("\\" + sectionLevels[0] + "*{Class Hierarchy}{"); os.println("\\thispagestyle{empty}"); os.println("\\markboth{Class Hierarchy}{Class Hierarchy}"); os.println("\\addcontentsline{toc}{" + sectionLevels[0] + "}{Class Hierarchy}"); // Classes ClassHierachy classHierachy = new ClassHierachy(); Enumeration<Package> f = map.elements(); while (f.hasMoreElements()) { final Package pkg = f.nextElement(); for (int i = 0; i < pkg.classes.size(); i++) { classHierachy.add(pkg.classes.get(i)); } } if (classHierachy.root.size() != 0) { os.println("\\" + sectionLevels[1] + "*{Classes}"); os.println("{\\raggedright"); classHierachy.printTree(root, overviewindent); os.println("}"); } // Interfaces InterfaceHierachy interfaceHierachy = new InterfaceHierachy(); f = map.elements(); while (f.hasMoreElements()) { final Package pkg = f.nextElement(); for (int i = 0; i < pkg.interfaces.size(); i++) { interfaceHierachy.add(pkg.interfaces.get(i)); } } if (interfaceHierachy.root.size() != 0) { os.println("\\" + sectionLevels[1] + "*{Interfaces}"); interfaceHierachy.printTree(root, overviewindent); } // Exceptions ClassHierachy exceptionHierachy = new ClassHierachy(); f = map.elements(); while (f.hasMoreElements()) { final Package pkg = f.nextElement(); for (int i = 0; i < pkg.exceptions.size(); i++) { exceptionHierachy.add(pkg.exceptions.get(i)); } } if (exceptionHierachy.root.size() != 0) { os.println("\\" + sectionLevels[1] + "*{Exceptions}"); exceptionHierachy.printTree(root, overviewindent); } // Errors ClassHierachy errorHierachy = new ClassHierachy(); f = map.elements(); while (f.hasMoreElements()) { final Package pkg = f.nextElement(); for (int i = 0; i < pkg.errors.size(); i++) { errorHierachy.add(pkg.errors.get(i)); } } if (errorHierachy.root.size() != 0) { os.println("\\" + sectionLevels[1] + "*{Errors}"); errorHierachy.printTree(root, overviewindent); } os.println("}"); } /** * Lays out a list of classes. * * @param type * Title of the section, e.g. "Interfaces", "Exceptions" etc. * @param classes * Vector of the classes to be laid out. */ static void layoutClasses(String type, List<ClassDoc> classes) { for (int i = 0; i < classes.size(); ++i) { ClassDoc cd = classes.get(i); // os.println( // "\\gdef\\classname{"+HTMLtoLaTeXBackEnd.fixText(cd.name())+"}" ); os.print("\\" + sectionLevels[1] + "{"); String mtype = "Class"; if (type.equals("Interfaces")) { mtype = "Interface"; } if (type.equals("Exceptions")) { mtype = "Exception"; } os.print("\\label{" + refName(makeRefKey(cd.qualifiedName())) + "}"); if (index) { if (cd.isInterface()) { os.print("\\index{" + HTMLtoLaTeXBackEnd.fixText(cd.name()) + "@" + ITALIC + " " + HTMLtoLaTeXBackEnd.fixText(cd.name()) + "}}"); } else { os.print("\\index{" + HTMLtoLaTeXBackEnd.fixText(cd.name()) + "}"); } } os.println(mtype + " " + HTMLtoLaTeXBackEnd.fixText(cd.name()) + "}{"); if (useHr) { os.println("\\rule[1em]{\\hsize}{4pt}\\vskip -1em"); } if (hyperref) { os.print("\\hypertarget{" + refName(makeRefKey(cd.qualifiedName())) + "}{}"); } os.println("\\vskip .1in "); if (cd.inlineTags().length > 0) { printTags(cd.containingPackage(), cd.inlineTags()); os.println("\\vskip .1in "); } SeeTag[] sees = cd.seeTags(); if (sees.length > 0) { os.println("\\" + sectionLevels[2] + "{See also}{}\n"); os.println(" \\begin{list}{-- }{\\setlength{\\itemsep}{0cm}\\setlength{\\parsep}{0cm}}"); for (int j = 0; j < sees.length; ++j) { os.print("\\item{ "); printSeesTag(sees[j], cd.containingPackage()); os.println("} "); } os.println(" \\end{list}"); } os.println("\\" + sectionLevels[2] + "{Declaration}{"); os.println("\\begin{lstlisting}[frame=" + classDeclarationFrame + "]"); os.print(cd.modifiers() + " "); if (cd.isInterface() == false) { os.print("class "); } os.println(cd.name()); ClassDoc sc = cd.superclass(); if (sc != null) { os.print(" extends " + sc.qualifiedName()); } ClassDoc intf[] = cd.interfaces(); if (intf.length > 0) { if (cd.isInterface() == false) { os.print(" implements "); } else { os.print(" extends "); } for (int j = 0; j < intf.length; ++j) { ClassDoc in = intf[j]; String nm; if (in.containingPackage().name() .equals(cd.containingPackage().name())) { nm = in.name(); } else { nm = in.qualifiedName(); } if (j > 0) { os.print(", "); } os.print(nm); } } os.println("\\end{lstlisting}"); ExecutableMemberDoc[] mems; FieldDoc[] flds; Tag[] verTags = cd.tags("version"); if (versioninfo && verTags.length > 0) { os.println("\\" + sectionLevels[2] + "{Version}{" + HTMLtoLaTeXBackEnd.fixText(verTags[0].text()) + "}"); } String subclasses = ""; for (int index = 0; index < theroot.classes().length; index++) { ClassDoc cls = theroot.classes()[index]; if (cls.subclassOf(cd) && !cls.equals(cd)) { if (!subclasses.equals("")) { subclasses += ", "; } subclasses += HTMLtoLaTeXBackEnd.fixText(cls.name()); subclasses += "\\small{\\refdefined{" + refName(makeRefKey(cls.qualifiedName())) + "}}"; } } if (cd.isInterface()) { if (!subclasses.equals("")) { os.println("\\" + sectionLevels[2] + "{All known subinterfaces}{" + subclasses + "}"); } } else { if (!subclasses.equals("")) { os.println("\\" + sectionLevels[2] + "{All known subclasses}{" + subclasses + "}"); } } String subintf = ""; String implclasses = ""; if (cd.isInterface()) { for (int index = 0; index < theroot.classes().length; index++) { ClassDoc cls = theroot.classes()[index]; boolean impls = false; for (int w = 0; w < cls.interfaces().length; w++) { ClassDoc intfDoc = cls.interfaces()[w]; if (intfDoc.equals(cd)) { impls = true; } } if (impls) { if (cls.isInterface()) { if (!subintf.equals("")) { subintf += ", "; } subintf += cls.name(); subintf += "\\small{\\refdefined{" + refName(makeRefKey(cls.qualifiedName())) + "}}"; } else { if (!implclasses.equals("")) { implclasses += ", "; } implclasses += cls.name(); implclasses += "\\small{\\refdefined{" + refName(makeRefKey(cls.qualifiedName())) + "}}"; } } } if (!implclasses.equals("")) { os.println("\\" + sectionLevels[2] + "{All classes known to implement interface}{" + implclasses + "}"); } } if (summaries) { flds = cd.fields(); if (flds.length > 0) { printFieldSummary(flds, "Field summary"); } if (useConstructorSummary) { mems = cd.constructors(); if (mems.length > 0) { printMethodSummary(mems, "Constructor summary"); } } if (useFieldSummary) { mems = cd.methods(); if (mems.length > 0) { printMethodSummary(mems, "Method summary"); } } } flds = cd.serializableFields(); if (flds.length > 0 && serial) { printFields(cd, flds, "Serializable Fields", false); } flds = cd.fields(); if (flds.length > 0) { printFields(cd, flds, "Fields", true); } mems = cd.constructors(); if (mems.length > 0) { os.println("\\" + sectionLevels[2] + "{Constructors}{"); printMembers(cd, mems, true); os.println("}"); } mems = cd.methods(); if (mems.length > 0) { os.println("\\" + sectionLevels[2] + "{Methods}{"); printMembers(cd, mems, true); os.println("}"); } if (inherited == true) { if (!cd.isInterface()) { ClassDoc par = cd.superclass(); while (par != null && par.qualifiedName().equals("java.lang.Object") == false) { printInherited(par); par = par.superclass(); } } else { List<ClassDoc> superclasses = new Vector<ClassDoc>(); while (getSuperClass(cd, superclasses) != null) { } superclasses = sortSuperclasses(superclasses); for (int m = superclasses.size() - 1; m >= 0; m--) { ClassDoc par = superclasses.get(m); printInherited(par); } } } os.println("}"); // os.print("\\newpage" ); } } /** * searches in all classes of the root doc for a superclass of the given * subsclass, that is not already in the list of superclasses adn adds it to * the list if found */ static ClassDoc getSuperClass(ClassDoc subclass, List<ClassDoc> superclasses) { ClassDoc[] cls = theroot.classes(); for (int n = 0; n < cls.length; ++n) { ClassDoc cd2 = cls[n]; if (subclass.subclassOf(cd2)) { if (subclass != cd2 && !superclasses.contains(cd2)) { superclasses.add(cd2); return cd2; } } } return null; } static List<ClassDoc> sortSuperclasses(List<ClassDoc> superclasses) { List<ClassDoc> result = new Vector<ClassDoc>(); int count = superclasses.size(); for (int k = 0; k < count; k++) { for (int i = 0; i < superclasses.size(); i++) { ClassDoc cd = superclasses.get(i); boolean isSubInterface = false; for (int j = 0; j < superclasses.size(); j++) { ClassDoc cd2 = superclasses.get(j); if (cd.subclassOf(cd2) && cd != cd2) { isSubInterface = true; break; } } if (!isSubInterface) { result.add(cd); superclasses.remove(cd); break; } } } return result; } /** * Enumerates the fields passed and formats them using Tex statements. * * @param flds * the fields to format */ static void printFields(ClassDoc cd, FieldDoc[] flds, String title, boolean labels) { boolean yet = false; for (int i = 0; i < flds.length; ++i) { FieldDoc f = flds[i]; if (!yet) { os.println("\\" + sectionLevels[2] + "{" + title + "}{"); if (useHr) { os.println("\\rule[1em]{\\hsize}{2pt}"); } os.println("\\begin{itemize}"); yet = true; } os.println("\\item{"); os.println("\\index{" + HTMLtoLaTeXBackEnd.fixText(f.name()) + "}"); if (labels) { os.print("\\label{" + refName(makeRefKey(f.qualifiedName())) + "}"); if (hyperref) { os.print("\\hypertarget{" + refName(makeRefKey(f.qualifiedName())) + "}{"); } } os.print(TRUETYPE); if (!cd.isInterface()) { os.print(HTMLtoLaTeXBackEnd.fixText(f.modifiers()) + " "); } os.print(HTMLtoLaTeXBackEnd.fixText(packageRelativIdentifier( f.containingPackage(), f.type().toString())) + "\\ "); os.print("" + BOLD + " " + HTMLtoLaTeXBackEnd.fixText(f.name()) + "}"); if (labels && hyperref) { os.println("}"); } // TRUETYPE ends os.println("}"); if (f.inlineTags().length > 0 || f.seeTags().length > 0) { os.println("\\begin{itemize}"); if (f.inlineTags().length > 0) { os.println("\\item{\\vskip -.9ex "); printTags(f.containingPackage(), f.inlineTags()); os.println("}"); } // See tags SeeTag[] sees = f.seeTags(); if (sees.length > 0) { os.println("\\item{{ See also}"); os.println(" \\begin{itemize}"); for (int j = 0; j < sees.length; ++j) { os.print("\\item{ "); printSeesTag(sees[j], f.containingPackage()); os.println("}"); } os.println(" \\end{itemize}"); os.println("}%end item"); } os.println("\\end{itemize}"); } os.println("}"); } if (yet) { os.println("\\end{itemize}"); os.println("}"); } } /** * Produces a constructor/method summary. * * @param dmems * The fields to be summarized. * @param title * The title of the section. */ static void printMethodSummary(ExecutableMemberDoc[] dmems, String title) { if (dmems.length == 0) { return; } os.println("\\" + sectionLevels[2] + "{" + title + "}{"); os.println("\\begin{verse}"); List<ExecutableMemberDoc> l = Arrays.asList(dmems); Collections.sort(l); Iterator<ExecutableMemberDoc> itr = l.iterator(); for (int i = 0; itr.hasNext(); ++i) { ExecutableMemberDoc mem = itr.next(); if (hyperref) { os.print("\\hyperlink{" + refName(makeRefKey(mem.qualifiedName() + mem.signature())) + "}{"); } os.print(BOLD + HTMLtoLaTeXBackEnd.fixText(mem.name() + mem.flatSignature()) + "}"); if (hyperref) { os.print("}"); } os.print(" "); printTags(mem.containingPackage(), mem.firstSentenceTags()); os.println("\\\\"); } os.println("\\end{verse}"); os.println("}"); } /** * Produces a field summary. * * @param dmems * The fields to be summarized. * @param title * The title of the section. */ static void printFieldSummary(FieldDoc[] dmems, String title) { if (dmems.length == 0) { return; } os.println("\\" + sectionLevels[2] + "{" + title + "}{"); os.println("\\begin{verse}"); List<FieldDoc> l = Arrays.asList(dmems); Collections.sort(l); Iterator<FieldDoc> itr = l.iterator(); for (int i = 0; itr.hasNext(); ++i) { FieldDoc mem = itr.next(); if (hyperref) { os.print("\\hyperlink{" + refName(makeRefKey(mem.qualifiedName())) + "}{"); } os.print(BOLD + HTMLtoLaTeXBackEnd.fixText(mem.name()) + "}"); if (hyperref) { os.print("}"); } os.print(" "); printTags(mem.containingPackage(), mem.firstSentenceTags()); os.println("\\\\"); } os.println("\\end{verse}"); os.println("}"); } /** * Enumerates the members of a section of the document and formats them * using Tex statements. */ static void printMembers(ClassDoc cd, ExecutableMemberDoc[] dmems, boolean labels) { if (dmems.length == 0) { return; } if (useHr) { os.println("\\rule[1em]{\\hsize}{2pt}\\vskip -2em"); } List<ExecutableMemberDoc> l = Arrays.asList(dmems); Collections.sort(l); Iterator<ExecutableMemberDoc> itr = l.iterator(); os.println("\\vskip -2em"); os.println("\\begin{itemize}"); for (int i = 0; itr.hasNext(); ++i) { ExecutableMemberDoc mem = itr.next(); if (i > 0) { if (useHr) { os.println("\\divideents{" + HTMLtoLaTeXBackEnd.fixText(mem.name()) + "}"); } } printMember(mem); } os.println("\\end{itemize}"); } /** * Enumerates the members of a section of the document and formats them * using Tex statements. */ static void printMember(ExecutableMemberDoc mem) { printMember(mem, null); } /** * Enumerates the members of a section of the document and formats them * using Tex statements. */ static void printMember(ExecutableMemberDoc mem, ExecutableMemberDoc copiedTo) { PackageDoc pac = copiedTo == null ? mem.containingPackage() : copiedTo .containingPackage(); if (mem instanceof MethodDoc) { MethodDoc method = (MethodDoc) mem; if (method.commentText() == "" && method.seeTags().length == 0 && method.throwsTags().length == 0 && method.paramTags().length == 0) { // No javadoc available for this method. Recurse through // superclasses // and implemented interfaces to find javadoc of overridden // methods. boolean found = false; ClassDoc doc = method.overriddenClass(); if (doc != null) { for (int i = 0; !found && i < doc.methods().length; ++i) { if (doc.methods()[i].name().equals(mem.name()) && doc.methods()[i].signature().equals( mem.signature())) { printMember(doc.methods()[i], copiedTo == null ? mem : copiedTo); found = true; } } } doc = method.containingClass(); for (int j = 0; !found && j < doc.interfaces().length; j++) { ClassDoc inf = doc.interfaces()[j]; for (int i = 0; !found && i < inf.methods().length; ++i) { if (inf.methods()[i].name().equals(mem.name()) && inf.methods()[i].signature().equals( mem.signature())) { printMember(inf.methods()[i], copiedTo == null ? mem : copiedTo); found = true; } } } if (found) { return; } } } ParamTag[] params = mem.paramTags(); // Some index and hyperref stuff // os.println("\\item{\\vskip -1.9ex " ); os.println("\\item{ "); os.println("\\index{" + HTMLtoLaTeXBackEnd.fixText(mem.name() + mem.flatSignature()) + "}"); if (hyperref) { if (copiedTo == null) { os.print("\\hypertarget{" + refName(makeRefKey(mem.qualifiedName() + mem.signature())) + "}{"); } else { os.print("\\hypertarget{" + refName(makeRefKey(copiedTo.qualifiedName() + copiedTo.signature())) + "}{"); } } os.print(BOLD + " " + HTMLtoLaTeXBackEnd.fixText(mem.name()) + "}\\\\"); if (hyperref) { os.print("}"); } os.println(); // Print signature os.println("\\begin{lstlisting}[frame=" + methodDeclarationFrame + "]"); if (!mem.containingClass().isInterface()) { os.print(mem.modifiers() + " "); } if (mem instanceof MethodDoc) { os.print(packageRelativIdentifier(pac, ((MethodDoc) mem) .returnType().toString()) + " "); } os.print(mem.name() + "("); Parameter[] parms = mem.parameters(); int p = 0; String qparmstr = ""; String parmstr = ""; for (; p < parms.length; ++p) { if (p > 0) { os.print(","); } Type t = parms[p].type(); os.print(packageRelativIdentifier(pac, t.qualifiedTypeName())); os.print(t.dimension()); if (parms[p].name().equals("") == false) { os.print(" " + parms[p].name()); } if (qparmstr.length() != 0) { qparmstr += ","; } qparmstr += t.qualifiedTypeName() + t.dimension(); if (parmstr.length() != 0) { parmstr += ","; } parmstr += t.typeName() + t.dimension(); } os.print(")"); // Thrown exceptions ClassDoc[] thrownExceptions = mem.thrownExceptions(); if (thrownExceptions != null && thrownExceptions.length > 0) { os.print(" throws " + thrownExceptions[0].qualifiedName()); for (int e = 1; e < thrownExceptions.length; e++) { os.print(", " + thrownExceptions[e].qualifiedName()); } } os.println("\\end{lstlisting} %end signature"); boolean yet = false; // Description if (mem.inlineTags().length > 0) { if (!yet) { os.println("\\begin{itemize}"); yet = true; } os.println("\\item{"); if (copiedTo == null) { os.println(BOLD + " Description}\n"); } else { os.print(BOLD + " Description copied from "); String classname = mem.containingClass().qualifiedName(); if (hyperref) { os.print("\\hyperlink{" + refName(makeRefKey(classname)) + "}{"); } os.print(packageRelativIdentifier(pac, classname)); if (hyperref) { os.print("}"); } os.print("{\\small "); os.print("\\refdefined{" + refName(makeRefKey(classname)) + "}"); os.println("} }\n"); } printTags(mem.containingPackage(), mem.inlineTags()); os.println("\n}"); } // Parameter tags if (params.length > 0) { if (!yet) { os.println("\\begin{itemize}"); yet = true; } os.println("\\item{"); os.println(BOLD + " Parameters}"); os.println(" \\begin{itemize}"); for (int j = 0; j < params.length; ++j) { os.println(" \\item{"); os.print(TRUETYPE + HTMLtoLaTeXBackEnd.fixText(params[j].parameterName()) + "}" + " -- "); printTags(mem.containingPackage(), params[j].inlineTags()); os.println("}"); } os.println(" \\end{itemize}"); os.println("}%end item"); } // Return tag if (mem instanceof MethodDoc) { Tag[] ret = mem.tags("return"); if (ret.length > 0) { if (!yet) { os.println("\\begin{itemize}"); yet = true; } os.println("\\item{" + BOLD + " Returns} -- "); for (int j = 0; j < ret.length; ++j) { printTags(mem.containingPackage(), ret[j].inlineTags()); os.println(" "); } os.println("}%end item"); } } // Throws or Exceptions tag if (mem instanceof ExecutableMemberDoc) { ThrowsTag[] excp = (mem).throwsTags(); if (excp.length > 0) { if (!yet) { os.println("\\begin{itemize}"); yet = true; } os.println("\\item{" + BOLD + " Throws}"); os.println(" \\begin{itemize}"); for (int j = 0; j < excp.length; ++j) { String ename = excp[j].exceptionName(); ClassDoc cdoc = excp[j].exception(); if (cdoc != null) { ename = cdoc.qualifiedName(); } os.print(" \\item{\\vskip -.6ex " + TRUETYPE + HTMLtoLaTeXBackEnd.fixText(ename) + "} -- "); printTags(mem.containingPackage(), excp[j].inlineTags()); os.println("}"); } os.println(" \\end{itemize}"); os.println("}%end item"); } } // See tags SeeTag[] sees = mem.seeTags(); if (sees.length > 0) { if (!yet) { os.println("\\begin{itemize}"); yet = true; } os.println("\\item{" + BOLD + " See also}"); os.println(" \\begin{itemize}"); for (int j = 0; j < sees.length; ++j) { os.print("\\item{ "); printSeesTag(sees[j], pac); os.println("}"); } os.println(" \\end{itemize}"); os.println("}%end item"); } if (yet) { os.println("\\end{itemize}"); } os.println("}%end item"); } /** * Prints class inheritance (list of members inherited from superclasses). * */ static void printInherited(ClassDoc par) { boolean members = false; MemberDoc[] inheritedmembers = new MemberDoc[par.fields().length + par.methods().length]; for (int k = 0; k < par.fields().length; k++) { inheritedmembers[k] = par.fields()[k]; members = true; } for (int k = 0; k < par.methods().length; k++) { inheritedmembers[k + par.fields().length] = par.methods()[k]; members = true; } if (members) { os.print("\\" + sectionLevels[2] + "{"); // do not user true type and do not print full name here // because this produces an ugly view in the Contents section // os.print("Members inherited from class "+TRUETYPE+"" os.print("Members inherited from class " + HTMLtoLaTeXBackEnd.fixText(par.name()) + " "); os.println("}{"); os.println(TRUETYPE + par.qualifiedName() + "} {\\small "); printRef(par.containingPackage(), par.name(), null); os.println("}"); os.println("{\\small "); printinheritedMembers(par, inheritedmembers, false); os.println("}"); } } /** * Enumerates the members of a section of the document and formats them * using Tex statements. * * @param mems * the members of this entity * @see #start */ static void printinheritedMembers(ClassDoc cd, MemberDoc[] dmems, boolean labels) { if (dmems.length == 0) { return; } os.println(); if (useHr) { os.println("\\rule[1em]{\\hsize}{2pt}\\vskip -2em"); } List<MemberDoc> l = Arrays.asList(dmems); Collections.sort(l); Iterator<MemberDoc> itr = l.iterator(); if (shortInheritance) { for (int i = 0; itr.hasNext(); ++i) { MemberDoc mem = itr.next(); // print only member names if (i != 0) { os.print(", "); } os.print(HTMLtoLaTeXBackEnd.fixText(mem.name())); } } else { os.println("\\vskip -2em"); os.println("\\begin{itemize}"); for (int i = 0; itr.hasNext(); ++i) { MemberDoc mem = itr.next(); // Print signature os.println("\\item{\\vskip -1.5ex "); os.print(TRUETYPE); os.print(HTMLtoLaTeXBackEnd.fixText(mem.modifiers())); if (mem instanceof MethodDoc) { os.print(" " + HTMLtoLaTeXBackEnd.fixText(((MethodDoc) mem) .returnType().typeName())); } os.print(" " + BOLD + " " + HTMLtoLaTeXBackEnd.fixText(mem.name()) + "}"); if (mem instanceof MethodDoc) { os.print("("); Parameter[] parms = ((MethodDoc) mem).parameters(); int p = 0; String qparmstr = ""; String parmstr = ""; for (; p < parms.length; ++p) { if (p > 0) { os.println(","); } Type t = parms[p].type(); os.print(TRUETYPE + HTMLtoLaTeXBackEnd .fixText(packageRelativIdentifier( mem.containingPackage(), t.qualifiedTypeName()))); os.print(HTMLtoLaTeXBackEnd.fixText(t.dimension()) + "}"); if (parms[p].name().equals("") == false) { os.print(" " + BOLD + " " + HTMLtoLaTeXBackEnd.fixText(parms[p] .name()) + "}"); } if (qparmstr.length() != 0) { qparmstr += ","; } qparmstr += t.qualifiedTypeName() + t.dimension(); if (parmstr.length() != 0) { parmstr += ","; } parmstr += t.typeName() + t.dimension(); } os.print(")"); // Thrown exceptions if (mem instanceof ExecutableMemberDoc) { ClassDoc[] thrownExceptions = ((ExecutableMemberDoc) mem) .thrownExceptions(); if (thrownExceptions != null && thrownExceptions.length > 0) { os.print(" throws " + packageRelativIdentifier( mem.containingPackage(), thrownExceptions[0].qualifiedName())); for (int e = 1; e < thrownExceptions.length; e++) { os.print(", " + thrownExceptions[e].qualifiedName()); } } } os.println(); if (labels && qparmstr.startsWith("field") == false) { os.print("\\label{" + refName(makeRefKey(cd.qualifiedName() + "." + mem.name() + ((qparmstr.length() > 0) ? ("(" + qparmstr + ")") : ""))) + "}"); os.print("\\label{" + refName(makeRefKey(cd.name() + "." + mem.name() + ((parmstr.length() > 0) ? ("(" + parmstr + ")") : ""))) + "}"); } } os.println("}%end signature"); boolean yet = false; if (yet) { os.println("\\end{itemize}"); } os.println("}%end item"); } os.println("\\end{itemize}"); } } /** * Prints a sequence of tags obtained from e.g. com.sun.javadoc.Doc.tags(). */ static void printTags(PackageDoc this_package, Tag[] tags) { String htmlstr = new String(); for (int i = 0; i < tags.length; i++) { if (tags[i] instanceof SeeTag) { SeeTag link = (SeeTag) tags[i]; String linkstr = ""; String label; if (link.referencedMember() != null) { MemberDoc member = link.referencedMember(); linkstr = member.qualifiedName(); label = classRelativeIdentifier(member.containingClass(), member.name()); if (link.referencedMember() instanceof ExecutableMemberDoc) { // If the member is a method, append the method // signature ExecutableMemberDoc m = (ExecutableMemberDoc) member; linkstr += m.signature(); label += m.flatSignature(); } } else if (link.referencedClass() != null) { linkstr = link.referencedClass().qualifiedName(); label = packageRelativIdentifier(this_package, link .referencedClass().name()); } else if (link.referencedPackage() != null) { linkstr = link.referencedPackage().name(); label = linkstr; } else { label = ""; } if (linkstr.isEmpty()) { htmlstr += link.text(); } else { // Encapsulate the link in a "TEX" tag and let // HTMLtoLaTeXBackEnd.fixText handle the rest. htmlstr += "<TEX txt=\"\\texttt{\\small "; if (hyperref) { htmlstr += "\\hyperlink{" + refName(makeRefKey(linkstr)) + "}{"; } if (!link.label().isEmpty()) { label = link.label(); } htmlstr += HTMLtoLaTeXBackEnd.fixText(label); if (hyperref) { htmlstr += "}"; } htmlstr += "}{\\small \n"; htmlstr += "\\refdefined{" + refName(makeRefKey(linkstr)) + "}"; htmlstr += "}"; htmlstr += "\"></TEX>"; } } else if ("@code".equals(tags[i].name())) { htmlstr += "<code>" + tags[i].text() + "</code>"; } else { htmlstr += tags[i].text(); } } os.print(HTMLtoLaTeXBackEnd.fixText(htmlstr)); } /** * Prints a reference to a package, class or member. */ static void printRef(PackageDoc pd, String cls, String mem) { String pkg = ""; if (pd != null) { pkg = pd.name() + "."; } String lbl = pkg + cls; if (mem != null && mem.equals("") == false) { lbl += "." + mem; } os.print("\\refdefined{" + refName(makeRefKey(lbl)) + "}"); } /** * Should be removed. */ static String makeRefKey(String key) { return key; } /** * Returns a package relative identifier. * * @param doc * The package the identifier should be relative to. * @param str * The identifier to be made relative. */ static String packageRelativIdentifier(PackageDoc doc, String str) { if (doc != null && str.startsWith(doc.name() + ".")) { return str.substring(doc.name().length() + 1); } else { return str; } } /** * Returns a class relative identifier. * * @param doc * The class the identifier should be relative to. * @param str * The identifier to be made relative. */ static String classRelativeIdentifier(ClassDoc doc, String str) { if (str.startsWith(doc.name())) { // This is a member or a method of the same class return str.substring(doc.name().length() + 1); } else if (str.startsWith(doc.containingPackage().name())) { // This is a member or a method of a different class but from the // same package return str.substring(doc.name().length() + 1); } else { // This is a member or a method from a different package, cannot be // simplified return str; } } /** * Prints a "see also" tag. * * @param tag * The "see also" tag to print. * @param relativeTo * The package to which the see tag should be relative to. */ static void printSeesTag(SeeTag tag, PackageDoc relativeTo) { String memName = ""; String memText = ""; if (tag.referencedMember() != null) { if (tag.referencedMember() instanceof ExecutableMemberDoc) { ExecutableMemberDoc m = (ExecutableMemberDoc) tag .referencedMember(); memName = m.qualifiedName() + m.signature(); memText = HTMLtoLaTeXBackEnd.fixText(packageRelativIdentifier( relativeTo, m.qualifiedName())); memText += "("; for (int i = 0; i < m.parameters().length; i++) { memText += HTMLtoLaTeXBackEnd .fixText(packageRelativIdentifier(relativeTo, m.parameters()[i].typeName())); if (i < m.parameters().length - 1) { memText += ",\\allowbreak "; } } memText += ")"; } else { memName = tag.referencedMember().qualifiedName(); memText = HTMLtoLaTeXBackEnd.fixText(packageRelativIdentifier( relativeTo, memName)); } } else if (tag.referencedClass() != null) { memName = tag.referencedClass().qualifiedName(); memText = HTMLtoLaTeXBackEnd.fixText(packageRelativIdentifier( relativeTo, memName)); } else if (tag.referencedPackage() != null) { memName = tag.referencedPackage().name(); memText = HTMLtoLaTeXBackEnd.fixText(memName); } if (memName.equals("") == false) { os.print(TRUETYPE); if (hyperref) { os.print("\\hyperlink{" + refName(makeRefKey(memName)) + "}{"); } // os.print(HTMLtoLaTeXBackEnd.fixText(memText)); // System.out.println("see also link : " + memText); os.print(memText); if (hyperref) { os.print("}"); } os.println("} {\\small "); os.print("\\refdefined{" + refName(makeRefKey(memName)) + "}"); os.println("}%end"); } else { os.print(HTMLtoLaTeXBackEnd.fixText(tag.text())); } } /** * In my opinion a PackageDoc should be able to tell where the source-files * defining the package were lifted from. The standard doclet uses this * directory to locate "doc-files" and copy them. Instead we have to attempt * to replicate the search procedure doclet API in order to locate the * appropriate directory. The following is not fool proof... */ static File findPackageDir(String pkg, RootDoc root) { File f = null; String sourcepath = null; for (int i = 0; i < root.options().length; i++) { if (root.options()[i][0].equalsIgnoreCase("-sourcepath")) { sourcepath = root.options()[i][1]; } } if (sourcepath == null) { sourcepath = "."; } else if (sourcepath.startsWith("\"")) { sourcepath = sourcepath.substring(1); if (sourcepath.endsWith("\"")) { sourcepath = sourcepath.substring(0, sourcepath.length() - 1); } } StringTokenizer sourcepathToken = new StringTokenizer(sourcepath, ";"); while (sourcepathToken.hasMoreTokens()) { String token = sourcepathToken.nextToken(); if (token.equals(".")) { f = null; } else { f = new File(token); } if (pkg != null && !pkg.equals("")) { StringTokenizer st = new StringTokenizer(pkg, "."); while (st.hasMoreTokens()) { f = new File(f, st.nextToken()); } } if (f.exists()) { // This test is necessary so we don't terminate prematurely. // It is, however, not sufficient. File[] javasourcefiles = f.listFiles(new FilenameFilter() { @Override public boolean accept(File file, String filename) { return filename.toLowerCase().endsWith(".java"); } }); if (javasourcefiles.length > 0) { return f; } } } return null; } static void finish() { if (os != null) { try { os.close(); } catch (Exception ex) { } } if (osPreamble != null) { try { osPreamble.close(); } catch (Exception ex) { } } try { FileOutputStream ostream = new FileOutputStream(outfile + ".map"); ObjectOutputStream p = new ObjectOutputStream(ostream); p.writeObject(refs); p.flush(); ostream.close(); if (createPdf) { createPdf(); createPdfHtmlWrapper(); } } catch (Exception ex) { ex.printStackTrace(); } } static void createPdf() throws IOException, InterruptedException { String cmd = PDFLATEX_CMD + outfile; // debuggin only // execute("pwd", null); for (int i = 0; i < PDFLATEX_ITERATIONS; i++) { execute(cmd, null, false); } } static void createPdfHtmlWrapper() throws IOException { String wrapperContent = HTML_PDF_WRAPPER.replace(REPLACE_OUT, outfile.replace(".tex", ".pdf")); wrapperContent = wrapperContent.replace(REPLACE_TITLE, outfile.replace(".tex", "")); FileWriter outFile = new FileWriter("index.html"); PrintWriter out = new PrintWriter(outFile); out.println(wrapperContent); out.close(); } static int execute(String cmd, String args[], boolean doOutput) throws IOException, InterruptedException { // some logging output : String argsString = ""; if (args != null) { argsString = Arrays.toString(args); } System.out.println("command to execute : " + cmd + " " + argsString); Process p; if (args == null) { p = Runtime.getRuntime().exec(cmd); } else { p = Runtime.getRuntime().exec(cmd, args); } // (?!?) if not reading p.getInputStream() stream, the process execution // seems to be endless and will never return for pdflatex command ! BufferedReader reader = new BufferedReader(new InputStreamReader( p.getInputStream())); String line = reader.readLine(); while (line != null) { if (doOutput) { System.out.println("> " + line); } line = reader.readLine(); } int res = -1; res = p.waitFor(); System.out.println("return code : " + res); return res; } }